//shared_ptr存在的问题
//shared_ptr内部维护了一个共享的引用计数器，多个shared_ptr可以指向同一个资源
//如果出现了循环引用的请款，引用计数器则无法归0，资源不会被释放

#include<memory>
#include<iostream>
#include<string>
#include<vector>
#include<functional>
using namespace std;
class BB;	//声明一下BB类
class AA
{
public:
	AA()
	{
		cout << m_name << "调用构造函数AA()。" << endl;
	}

	AA(const string& name) :m_name(name)
	{
		cout << "调用构造函数AA(" << m_name << ") " << endl;	// "<<变量名<<"
	}

	~AA()
	{
		cout << "调用了析构函数~AA(" << m_name << ")" << endl;
	}
	string m_name;
	shared_ptr<BB> m_p;
};

class BB
{
public:
	string m_name;
	shared_ptr<AA> m_p;
	BB()
	{
		cout << "调用构造函数BB()。" << endl;
	}
	BB(const string& name) :m_name(name)
	{
		cout << "调用构造函数BB(" << m_name << ")。" << endl;
	}
	~BB()
	{
		cout << "调用析构函数~BB(" << m_name << ")。" << endl;
	}
};

int main()
{
	shared_ptr<AA> pa = make_shared<AA>("Tom");
	shared_ptr<BB> pb = make_shared<BB>("Jerry");

	pa->m_p = pb;	//AA类的m_p成员指向BB类资源
	pb->m_p = pa;	//BB类的m_p成员指向AA类资源
	//运行结果不会调用析构函数
    //将m_p的类型改为weak_ptr即可解决这一问题
	return 0;
}





//weak_ptr是为了配合shared_ptr而引入的，它指向的一个由shared_ptr管理的资源，但不影响资源的生命周期
//也就是说，将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计时器
int main()
{
	shared_ptr<AA> pa = make_shared<AA>("Tom");
	shared_ptr<BB> pb = make_shared<BB>("Jerry");

	cout << "pa.use_count() = " << pa.use_count() << endl;
	cout << "pb.use_count() = " << pb.use_count() << endl;

	pa->m_p = pb;	
	pb->m_p = pa;	
	
	cout << "pa.use_count() = " << pa.use_count() << endl;
	cout << "pb.use_count() = " << pb.use_count() << endl;  //均为1

	return 0;
}







//weak_ptr使用方法
//weak_ptr没有重载->和*(解引用)操作符，不能直接访问资源

//用=可以把shared_ptr或者weak_ptr赋值给weak_ptr
//.expired();		//判断它所指资源是否过期或被销毁
//.lock();			//返回shared_ptr，如果资源已过期，则返回空的shared_ptr
//.reset();			//将当前weak_ptr指针置为空
//.swap();			//交换

int main()
{
	shared_ptr<AA> pa = make_shared<AA>("Tom");

	//语句块
	{
		shared_ptr<BB> pb = make_shared<BB>("Jerry");
		
		pa->m_p = pb;
		pb->m_p = pa;

		if (pa->m_p.expired() == true)
			cout << "语句块内部:pa->m_p已过期。" << endl;
		else
			cout << "语句块内部: pa->m_p.lock()->m_name : " << pa->m_p.lock()->m_name << endl;
	}
	
	if (pa->m_p.expired() == true)
		cout << "语句块外部:pa->m_p已过期。" << endl;
	else
		cout << "语句块外部: pa->m_p.lock()->m_name : " << pa->m_p.lock()->m_name << endl;

	return 0;
}
/*
调用构造函数AA(Tom)
调用构造函数BB(Jerry)。
语句块内部: pa->m_p.lock()->m_name : Jerry
调用析构函数~BB(Jerry)。
语句块外部:pa->m_p已过期。
调用了析构函数~AA(Tom)
*/






//更深层次，实际开发中shared_ptr和weak_ptr主要用于多线程程序中，单线程中几乎不用
//weak_ptr不控制对象的生命周期，但是，它知道对象是否还或者
//用lock()函数把它提升为shared_ptr，如果对象还或者，返回有效的shared_ptr，如果对象已经死了，提升失败，返回一个空的shared_ptr
//提升的行为（lock()）是线程安全的


    //之前的代码并不正确
	//语句块内部的ifelse语句并不是原子的，先判断m_p是否过期，如果没过期则输出m_name
	//资源可能在可能判断和输出之间，被其他线程释放了，因此代码实际有错


//以下才是正确代码
int main()
{
	shared_ptr<AA> pa = make_shared<AA>("Tom");

	//语句块
	{
		shared_ptr<BB> pb = make_shared<BB>("Jerry");

		pa->m_p = pb;
		pb->m_p = pa;
		shared_ptr<BB> pp = pa->m_p.lock();	//把weak_ptr提升为shared_ptr
		//lock()是线程安全的原子函数

		if (pp == nullptr)
			cout << "语句块内部:pa->m_p已过期。" << endl;
		else
			cout << "语句块内部: pp->m_p.lock()->m_name : " << pp->m_name << endl;
	}

	shared_ptr<BB> pp = pa->m_p.lock();
	if (pp == nullptr)
		cout << "语句块外部:pa->m_p已过期。" << endl;
	else
		cout << "语句块外部: pp->m_name : " << pp->m_name << endl;

	return 0;
}
//运行结果和之前一样